# This Python file uses the following encoding: utf-8

# if __name__ == "__main__":
#     pass
#!/usr/bin/env python3

import cv2
import socket
import struct
import time

def release_camera():
    """尝试释放摄像头资源"""
    try:
        print("尝试关闭摄像头")
        cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
        if cap.isOpened():
            cap.release()
            print("已关闭已打开的摄像头")
    except Exception as e:
        print("关闭摄像头时出错:", e)

def check_camera_available():
    """检查摄像头是否可用"""
    try:
        cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
        if not cap.isOpened():
            print("摄像头不可用")
            return False
        cap.release()
        return True
    except Exception as e:
        print("检查摄像头时出错:", e)
        return False

def check_port_available(port):
    """检查端口是否被占用"""
    try:
        test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        test_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        test_socket.bind(('0.0.0.0', port))
        test_socket.close()
        return True
    except socket.error:
        print(f"端口 {port} 被占用")
        return False

def main():
    # 检查摄像头是否可用
    if not check_camera_available():
        print("摄像头不可用，退出程序")
        return

    # 检查端口是否被占用
    if not check_port_available(5000):
        print("端口被占用，退出程序")
        return

    # 初始化摄像头
    cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
    if not cap.isOpened():
        print("无法打开摄像头")
        return

    # 测试捕获一帧
    ret, frame = cap.read()
    if not ret:
        print("无法读取摄像头帧")
        cap.release()
        return
    else:
        print("摄像头初始化成功")

    # 设置摄像头参数
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
    cap.set(cv2.CAP_PROP_FPS, 15)
    # ------------------------- 优化点 2：动态帧率控制 -------------------------
    TARGET_FPS = 10                          # 进一步降低帧率
    FRAME_INTERVAL = 1.0 / TARGET_FPS
    
    # 创建 Socket 服务器
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(('0.0.0.0', 5000))
    server_socket.listen(5)
    print("等待客户端连接...")

    try:
        while True:  # 外层循环：持续等待新客户端连接
            client_socket = None
            try:
                # 接受客户端连接
                client_socket, addr = server_socket.accept()
                print("连接来自:", addr)
            # ------------------------- 优化点 3：压缩质量调整 -------------------------
                JPEG_QUALITY = 40  # 从 50 降至 40（更低带宽）

                last_frame_time = time.time()  # 记录上一帧时间
                while True:  # 内层循环：处理当前客户端的数据流
                    try:
                        current_time = time.time()
                        elapsed = current_time - last_frame_time

                    # 控制帧率：等待到下一帧时间
                        if elapsed < FRAME_INTERVAL:
                            time.sleep(FRAME_INTERVAL - elapsed)
                        ret, frame = cap.read()
                        if not ret:
                            print("无法读取帧")
                            break

                    # ------------------------- 优化点 4：缩小分辨率（二次压缩）-------------------------
                        small_frame = cv2.resize(frame, (160, 120))  # 进一步缩小到 160x120

                    # 压缩帧为 JPEG（使用调整后的质量）
                        success, jpeg_buffer = cv2.imencode('.jpg', small_frame, [cv2.IMWRITE_JPEG_QUALITY, JPEG_QUALITY])
                        if not success:
                            print("JPEG 编码失败")
                            break

                        # 发送数据
                        jpeg_bytes = jpeg_buffer.tobytes()
                        message = struct.pack("<Q", len(jpeg_bytes)) + jpeg_bytes
                        try:
                            client_socket.sendall(message)
                            last_frame_time = time.time()  # 更新帧时间戳
#                            print(f"发送帧数据，大小: {len(jpeg_bytes)} 字节")
                        except (ConnectionResetError, BrokenPipeError) as e:
                            print(f"客户端断开连接: {e}")
                            break  # 退出内层循环

                    except Exception as e:
                        print(f"处理数据时发生错误: {e}")
                        break  # 退出内层循环

            except KeyboardInterrupt:
                print("服务端手动退出")
                break  # 退出外层循环

            except Exception as e:
                print(f"接受客户端连接时发生错误: {e}")

            finally:
                # 清理当前客户端连接
                if client_socket:
                    client_socket.close()
                    print("客户端连接已关闭")

    finally:
        # 释放所有资源
        cap.release()
        server_socket.close()
        print("所有资源已释放")

if __name__ == "__main__":
    main()
